package control;

import entidad.Medicion;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtilities;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class TrazarGraficas {
    
    //variables de la clase
    public enum tipo{pluviosidad,presion,temperatura};
    
    private int ANCHO_GRAFICA = 400;
    private int ALTO_GRAFICA = 300;   
    //índices: 0 para pluviosidad, 1 para presion y 2 para temperatura
    private double[] ymax={-214748364,-214748364,-214748364};
    private double[] ymin={214748364,214748364,214748364};
    private int num=0;
    private Color COLOR_SERIE_1 = new Color(255, 128, 64);
    private Color COLOR_RECUADROS_GRAFICA = new Color(150,150,150);
    private Color COLOR_FONDO_GRAFICA = new Color(238, 238, 238);
    private ArrayList<Medicion> datos;
    private XYSeriesCollection collectionPluviosidad;
    private XYSeriesCollection collectionPresion;
    private XYSeriesCollection collectionTemperatura;    
    
    public TrazarGraficas(ArrayList<Medicion> d) {
        datos=d;
        
        //Se pasa la información del arraylist de entrada
        //a un formato reconocido para la libreria de gráficas, es decir,
        //a un XYSeriesCollection
        
        //un XYSeriesCollection se compone de una o más XYSeries
        
        XYSeries seriePluviosidad = new XYSeries("Pluviosidad");
        XYSeries seriePresion = new XYSeries("Presion");        
        XYSeries serieTemperatura = new XYSeries("Temperatura");
          
        for(Medicion m:datos) {
            seriePluviosidad.add(m.getId(), m.getPluviosidad());
            seriePresion.add(m.getId(), m.getPresion());
            serieTemperatura.add(m.getId(), m.getTemperatura());
            
            if(m.getPluviosidad()>ymax[0]) {ymax[0]=m.getPluviosidad();}
            if(m.getPresion()>ymax[1]) {ymax[1]=m.getPresion();}
            if(m.getTemperatura()>ymax[2]) {ymax[2]=m.getTemperatura();}
            
            if(m.getPluviosidad()<ymin[0]) {ymin[0]=m.getPluviosidad();}
            if(m.getPresion()<ymin[1]) {ymin[1]=m.getPresion();}
            if(m.getTemperatura()<ymin[2]) {ymin[2]=m.getTemperatura();}   
            
            num++;
        }
               
        collectionPluviosidad = new XYSeriesCollection();
        collectionPluviosidad.addSeries(seriePluviosidad);
        collectionPresion = new XYSeriesCollection();
        collectionPresion.addSeries(seriePresion);     
        collectionTemperatura = new XYSeriesCollection();
        collectionTemperatura.addSeries(serieTemperatura);         
    }

    public void crearGrafica(tipo var, String titulo, String labelVertical, String labelHorizontal, String nombreArchivo) throws IOException {
        XYSeriesCollection dataset=null;
        double min=-50,max=50;
        switch(var){
            case pluviosidad:
                dataset=collectionPluviosidad;
                COLOR_SERIE_1=new Color(70, 130, 180);
                max=ymax[0]+(ymax[0]*0.1);min=ymin[0];
                break;
            case presion:
                dataset=collectionPresion;
                COLOR_SERIE_1=new Color(46, 139, 87);
                max=ymax[1]+(ymax[1]*0.1);min=ymin[1];
                break;
            case temperatura:
                dataset=collectionTemperatura;
                COLOR_SERIE_1=new Color(255, 128, 64);
                max=ymax[2]+(ymax[2]*0.1);min=ymin[2];
                break;
        }
        //Finalmente, se crea la gráfica con la información recibida
        JFreeChart chart = ChartFactory.createXYLineChart(titulo, labelVertical, labelHorizontal, 
                dataset,//información de la tabla
                PlotOrientation.VERTICAL, 
                true, // uso de leyenda
                false, // uso de tooltips  
                false // uso de urls
                );
        // color de fondo de la gráfica
        chart.setBackgroundPaint(COLOR_FONDO_GRAFICA);
 
        XYPlot plot = (XYPlot) chart.getPlot();
        configurarPlot(plot);
 
        NumberAxis domainAxis = (NumberAxis)plot.getDomainAxis();
        configurarDomainAxis(domainAxis);
         
        NumberAxis rangeAxis = (NumberAxis)plot.getRangeAxis();
        configurarRangeAxis(rangeAxis,min,max);
 
        XYLineAndShapeRenderer renderer = (XYLineAndShapeRenderer)plot.getRenderer();
        configurarRendered(renderer);
        
        ChartUtilities.saveChartAsPNG(new File(nombreArchivo),chart, ANCHO_GRAFICA, ALTO_GRAFICA);
 
    }
     
    // configuramos el contenido del gráfico (damos un color a las líneas que sirven de guía)
    private void configurarPlot (XYPlot plot) {
        plot.setDomainGridlinePaint(COLOR_RECUADROS_GRAFICA);
        plot.setRangeGridlinePaint(COLOR_RECUADROS_GRAFICA);
    }
     
    // configuramos el eje X de la gráfica (se muestran números enteros y de uno en uno)
    private void configurarDomainAxis (NumberAxis domainAxis) {
        domainAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        if(num<10) domainAxis.setTickUnit(new NumberTickUnit(1));
        else domainAxis.setTickUnit(new NumberTickUnit((int)(num/10)));
    }
     
    // configuramos el eje y de la gráfica 
    private void configurarRangeAxis (NumberAxis rangeAxis, double min,double max) {
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        if(min*max<0) {
            if((int)(max-min)<10)  rangeAxis.setTickUnit(new NumberTickUnit(1));
            else rangeAxis.setTickUnit(new NumberTickUnit((int)((max-min)/10)));
        }
        else {
            if((int)(Math.abs(max)+Math.abs(min))<10) rangeAxis.setTickUnit(new NumberTickUnit(1));
            else rangeAxis.setTickUnit(new NumberTickUnit((int)((Math.abs(max)+Math.abs(min))/10)));
        }
        
        rangeAxis.setRange(min+(min*0.2)-2,max+2);
        if(min>0) rangeAxis.setRange(0,max+2);
        System.out.println(min);
    }
     
    // configuramos las líneas de las series (añadimos un círculo en los puntos y asignamos el color de cada serie)
    private void configurarRendered (XYLineAndShapeRenderer renderer) {
        renderer.setSeriesShapesVisible(0, true);
        renderer.setSeriesPaint(0, COLOR_SERIE_1);
    }

}